use crate::config::AppConfig;
use crate::crawler::CrawlerEngine;
use crate::error::{AppError, Result};
use crate::models::*;
use crate::utils::{ExportManager, SystemUtils};
use crate::AppState;
use parking_lot::RwLock;
use std::collections::HashMap;
use std::sync::Arc;
use tauri::State;
use tokio::sync::Mutex;

// 全局爬虫引擎实例
static CRAWLER_ENGINE: once_cell::sync::Lazy<Arc<RwLock<Option<CrawlerEngine>>>> =
    once_cell::sync::Lazy::new(|| Arc::new(RwLock::new(None)));

// 日志相关静态变量
static LOGS: once_cell::sync::Lazy<Arc<Mutex<Vec<LogEntry>>>> =
    once_cell::sync::Lazy::new(|| Arc::new(Mutex::new(Vec::new())));

// 配置相关命令
#[tauri::command]
pub async fn get_config(state: State<'_, AppState>) -> Result<AppConfig> {
    let config = state.config.lock().await;
    Ok(config.clone())
}

#[tauri::command]
pub async fn update_config(
    state: State<'_, AppState>,
    config: AppConfig,
) -> Result<()> {
    let mut current_config = state.config.lock().await;
    *current_config = config;
    Ok(())
}

#[tauri::command]
pub async fn save_config(state: State<'_, AppState>) -> Result<()> {
    let config = state.config.lock().await;
    config.save().await?;
    Ok(())
}

#[tauri::command]
pub async fn reset_config(state: State<'_, AppState>) -> Result<AppConfig> {
    let new_config = AppConfig::reset().await?;
    let mut current_config = state.config.lock().await;
    *current_config = new_config.clone();
    Ok(new_config)
}

// 任务相关命令
#[tauri::command]
pub async fn submit_task(
    state: State<'_, AppState>,
    config: serde_json::Value,
) -> Result<String> {
    println!("🚀 [Tauri] submit_task 命令被调用");
    add_log("info", "🚀 开始提交任务...").await;
    
    println!("📋 [Tauri] 接收到的配置: {}", config);
    
    // 解析配置
    let platform = config["platform"].as_str().unwrap_or("zhihu");
    let _keywords = config["keywords"].as_str().unwrap_or("");
    let _crawl_count = config["crawl_count"].as_i64().unwrap_or(100) as i32;
    let crawler_type = config["crawler_type"].as_str().unwrap_or("search");
    let task_name = config["task_name"].as_str().unwrap_or("新任务");
    
    println!("🔍 [Tauri] 解析后的配置: platform={}, keywords={}, count={}, type={}", 
             platform, _keywords, _crawl_count, crawler_type);
    
    // 验证平台和关键词
    if _keywords.is_empty() {
        let error_msg = "❌ 关键词不能为空";
        println!("{}", error_msg);
        add_log("error", error_msg).await;
        return Err(AppError::Unknown("关键词不能为空".to_string()));
    }
    
    // 创建任务记录
    let crawler_config = CrawlerConfig {
        platform: platform.to_string(),
        crawler_type: crawler_type.to_string(),
        login_type: "qrcode".to_string(),
        save_data_option: "sqlite".to_string(),
        keywords: _keywords.to_string(),
        crawl_count: _crawl_count,
        start_page: config["start_page"].as_i64().unwrap_or(1) as i32,
        concurrency: config["concurrency"].as_i64().unwrap_or(3) as i32,
        enable_comments: config["enable_comments"].as_bool().unwrap_or(false),
        enable_sub_comments: config["enable_sub_comments"].as_bool().unwrap_or(false),
        enable_media: config["enable_media"].as_bool().unwrap_or(false),
        enable_proxy: config["enable_proxy"].as_bool().unwrap_or(false),
    };
    
    // 创建任务
    let task = Task::new(
        task_name,
        platform,
        crawler_type,
        &_keywords,
        &crawler_config
    );
    
    // 保存任务到数据库
    state.database.insert_task(&task).await?;
    
    // 创建任务日志
    let task_log = TaskLog::new(
        &task.id,
        "info",
        &format!("任务已创建: {}", task_name)
    );
    
    // 保存任务日志
    state.database.insert_task_log(&task_log).await?;
    
    // 异步启动任务
    let task_id = task.id.clone();
    let db = state.database.clone();
    let config_clone = config.clone();
    
    tokio::spawn(async move {
        // 更新任务状态为运行中
        let _ = db.update_task_status(&task_id, "running").await;
        
        // 启动爬虫
        match start_crawler_process(config_clone).await {
            Ok(_) => {
                // 任务完成
                let _ = db.update_task_status(&task_id, "completed").await;
                let _ = db.insert_task_log(&TaskLog::new(
                    &task_id,
                    "info",
                    "任务已完成"
                )).await;
            },
            Err(e) => {
                // 任务失败
                let _ = db.update_task_status(&task_id, "failed").await;
                let _ = db.update_task_error(&task_id, &e.to_string()).await;
                let _ = db.insert_task_log(&TaskLog::new(
                    &task_id,
                    "error",
                    &format!("任务失败: {}", e)
                )).await;
            }
        }
    });
    
    Ok(task.id)
}

#[tauri::command]
pub async fn get_task_list(
    state: State<'_, AppState>,
) -> Result<Vec<Task>> {
    state.database.get_all_tasks().await
}

#[tauri::command]
pub async fn get_task_by_id(
    state: State<'_, AppState>,
    task_id: String,
) -> Result<Option<Task>> {
    state.database.get_task_by_id(&task_id).await
}

#[tauri::command]
pub async fn pause_task(
    state: State<'_, AppState>,
    task_id: String,
) -> Result<()> {
    state.database.update_task_status(&task_id, "paused").await?;
    
    // 如果是当前运行的任务，暂停爬虫
    if let Some(engine) = CRAWLER_ENGINE.read().as_ref() {
        engine.pause();
    }
    
    Ok(())
}

#[tauri::command]
pub async fn resume_task(
    state: State<'_, AppState>,
    task_id: String,
) -> Result<()> {
    state.database.update_task_status(&task_id, "running").await?;
    
    // 如果是当前运行的任务，恢复爬虫
    if let Some(engine) = CRAWLER_ENGINE.read().as_ref() {
        engine.resume();
    }
    
    Ok(())
}

#[tauri::command]
pub async fn stop_task(
    state: State<'_, AppState>,
    task_id: String,
) -> Result<()> {
    state.database.update_task_status(&task_id, "stopped").await?;
    
    // 如果是当前运行的任务，停止爬虫
    if let Some(engine) = CRAWLER_ENGINE.read().as_ref() {
        engine.stop();
    }
    
    Ok(())
}

#[tauri::command]
pub async fn get_task_logs(
    state: State<'_, AppState>,
    task_id: String,
) -> Result<Vec<TaskLog>> {
    state.database.get_task_logs(&task_id, 1000).await
}

#[tauri::command]
pub async fn export_task_logs(
    state: State<'_, AppState>,
    task_id: String,
    file_path: String,
) -> Result<()> {
    let logs = state.database.get_task_logs(&task_id, 10000).await?;
    let content = logs
        .iter()
        .map(|log| format!("[{}] {}: {}", log.created_at, log.level, log.message))
        .collect::<Vec<_>>()
        .join("\n");
    
    tokio::fs::write(file_path, content).await?;
    Ok(())
}

// 爬虫相关命令
#[tauri::command]
pub async fn start_crawler(
    config: serde_json::Value,
) -> Result<()> {
    println!("🚀 [Tauri] start_crawler 命令被调用");
    add_log("info", "🚀 开始启动爬虫...").await;
    
    // 调用内部函数启动爬虫进程
    start_crawler_process(config).await
}

#[tauri::command]
pub async fn pause_crawler() -> Result<()> {
    if let Some(engine) = CRAWLER_ENGINE.read().as_ref() {
        engine.pause();
    }
    Ok(())
}

#[tauri::command]
pub async fn stop_crawler() -> Result<()> {
    if let Some(engine) = CRAWLER_ENGINE.read().as_ref() {
        engine.stop();
    }
    Ok(())
}

#[tauri::command]
pub async fn get_crawler_status() -> Result<CrawlerStatus> {
    if let Some(engine) = CRAWLER_ENGINE.read().as_ref() {
        Ok(engine.get_status())
    } else {
        Ok(CrawlerStatus::default())
    }
}

// 数据相关命令
#[tauri::command]
pub async fn get_data_overview(state: State<'_, AppState>) -> Result<Vec<DataOverview>> {
    state.database.get_data_overview().await
}

#[tauri::command]
pub async fn get_data_list(
    state: State<'_, AppState>,
    platform: Option<String>,
    page: i32,
    page_size: i32,
) -> Result<Vec<CrawledData>> {
    let offset = (page - 1) * page_size;
    state
        .database
        .get_data_list(platform.as_deref(), page_size, offset)
        .await
}

#[tauri::command]
pub async fn export_data(
    state: State<'_, AppState>,
    options: ExportOptions,
    file_path: String,
) -> Result<()> {
    let data = state
        .database
        .get_data_list(None, 10000, 0) // 获取所有数据
        .await?;
    
    let path = std::path::Path::new(&file_path);
    
    match options.format.as_str() {
        "csv" => ExportManager::export_to_csv(&data, path).await?,
        "json" => ExportManager::export_to_json(&data, path).await?,
        "excel" => ExportManager::export_to_excel(&data, path).await?,
        _ => return Err(AppError::Unknown("Unsupported export format".to_string())),
    }
    
    Ok(())
}

#[tauri::command]
pub async fn delete_data(
    state: State<'_, AppState>,
    ids: Vec<String>,
) -> Result<i32> {
    state.database.delete_data(ids).await
}

// 日志相关命令
#[tauri::command]
pub async fn get_logs() -> Result<Vec<LogEntry>> {
    let logs = LOGS.lock().await;
    Ok(logs.clone())
}

#[tauri::command]
pub async fn get_python_logs() -> Result<Vec<LogEntry>> {
    let logs = LOGS.lock().await;
    // 返回所有Python相关的日志
    let python_logs: Vec<LogEntry> = logs
        .iter()
        .filter(|log| {
            let msg = &log.message;
            // 只保留Python相关的日志，包括Python进程的输出
            (msg.contains("Python") || 
             msg.contains("[Python") || 
             msg.contains("python") || 
             msg.contains("爬虫") || 
             msg.contains("crawler") || 
             msg.contains("INFO:") || 
             msg.contains("ERROR:") || 
             msg.contains("WARNING:")) && 
            msg.trim().len() > 0
        })
        .cloned()
        .collect();
    Ok(python_logs)
}

#[tauri::command]
pub async fn clear_logs() -> Result<()> {
    let mut logs = LOGS.lock().await;
    logs.clear();
    Ok(())
}

#[tauri::command]
pub async fn export_logs(file_path: String) -> Result<()> {
    let logs = LOGS.lock().await;
    let content = logs
        .iter()
        .map(|log| format!("[{}] {}: {}", log.time, log.level, log.message))
        .collect::<Vec<_>>()
        .join("\n");
    
    tokio::fs::write(file_path, content).await?;
    Ok(())
}

// 统计相关命令
#[tauri::command]
pub async fn get_statistics(state: State<'_, AppState>) -> Result<HashMap<String, i32>> {
    let mut stats = HashMap::new();
    
    let total_count = state.database.get_data_count(None).await?;
    stats.insert("total_data".to_string(), total_count);
    
    let platforms = ["xhs", "douyin", "kuaishou", "bilibili", "weibo", "zhihu", "tieba"];
    for platform in platforms {
        let count = state.database.get_data_count(Some(platform)).await?;
        stats.insert(platform.to_string(), count);
    }
    
    Ok(stats)
}

#[tauri::command]
pub async fn get_platform_stats(state: State<'_, AppState>) -> Result<Vec<PlatformStats>> {
    state.database.get_platform_stats().await
}

// 系统相关命令
#[tauri::command]
pub async fn get_system_info() -> Result<SystemInfo> {
    Ok(SystemUtils::get_system_info())
}

#[tauri::command]
pub async fn open_data_folder() -> Result<()> {
    let data_dir = dirs::data_dir()
        .ok_or_else(|| AppError::Unknown("Failed to get data directory".to_string()))?
        .join("mediacrawler-gui");
    
    SystemUtils::open_folder(&data_dir.to_string_lossy()).await
}

#[tauri::command]
pub async fn check_for_updates() -> Result<String> {
    // 这里可以实现更新检查逻辑
    Ok("当前已是最新版本".to_string())
}

// 文件操作命令
#[tauri::command]
pub async fn select_folder() -> Result<Option<String>> {
    // 这里需要使用 tauri 的文件对话框 API
    Ok(Some("./data".to_string()))
}

#[tauri::command]
pub async fn select_file() -> Result<Option<String>> {
    // 这里需要使用 tauri 的文件对话框 API
    Ok(Some("./config.json".to_string()))
}

#[tauri::command]
pub async fn save_file(content: String, default_name: String) -> Result<Option<String>> {
    // 这里需要使用 tauri 的文件保存对话框 API
    let file_path = format!("./exports/{}", default_name);
    tokio::fs::write(&file_path, content).await?;
    Ok(Some(file_path))
}

// 监控爬虫进程
async fn monitor_crawler_process() {
    let mut interval = tokio::time::interval(tokio::time::Duration::from_secs(3));
    let mut last_status = false;
    let mut check_count = 0;
    
    println!("🔍 [Tauri] 开始监控Python进程状态...");
    add_log("info", "🔍 开始监控Python进程状态...").await;
    
    loop {
        interval.tick().await;
        check_count += 1;
        
        // 检查进程状态
        let (is_running, process_exists) = if let Some(engine) = CRAWLER_ENGINE.read().as_ref() {
            let status = engine.get_status();
            
            // 使用CrawlerEngine的公共方法检查进程状态
            let process_exists = engine.is_process_alive();
            
            (status.is_running, process_exists)
        } else {
            (false, false)
        };
        
        // 状态变化时记录日志
        if is_running != last_status {
            if is_running {
                println!("✅ [Tauri] Python进程状态: 运行中");
                add_log("info", "✅ Python进程状态: 运行中").await;
            } else {
                println!("⏹️ [Tauri] Python进程状态: 已停止");
                add_log("info", "⏹️ Python进程状态: 已停止").await;
            }
            last_status = is_running;
        }
        
        // 每30秒输出一次状态信息（用于调试）
        if check_count % 10 == 0 {
            println!("📊 [Tauri] 进程监控状态: 运行={}, 进程存在={}, 检查次数={}", 
                     is_running, process_exists, check_count);
        }
        
        // 如果进程不再运行，退出监控
        if !is_running && !process_exists {
            println!("🔚 [Tauri] Python进程已完全停止，结束监控");
            add_log("info", "🔚 Python进程监控结束").await;
            break;
        }
    }
}

// 添加日志的辅助函数
pub async fn add_log(level: &str, message: &str) {
    let mut logs = LOGS.lock().await;
    logs.push(LogEntry {
        time: chrono::Utc::now().format("%H:%M:%S").to_string(),
        level: level.to_string(),
        message: message.to_string(),
    });
    
    // 限制日志数量
    if logs.len() > 1000 {
        logs.drain(0..500);
    }
}

// 启动爬虫进程的内部函数
async fn start_crawler_process(config: serde_json::Value) -> Result<()> {
    println!("🚀 [Tauri] start_crawler_process 函数被调用");
    add_log("info", "🚀 开始启动爬虫进程...").await;
    
    // 解析配置
    let platform = config["platform"].as_str().unwrap_or("zhihu");
    let keywords = config["keywords"].as_str().unwrap_or("");
    let crawl_count = config["crawl_count"].as_i64().unwrap_or(100) as i32;
    let crawler_type = config["crawler_type"].as_str().unwrap_or("search");
    
    // 获取脚本路径，支持自定义路径或使用默认路径
    let script_path = config["scriptPath"].as_str().unwrap_or("main.py");
    
    // 尝试多个可能的路径
    let possible_paths = vec![
        script_path.to_string(),                // 用户提供的路径
        format!("../{}", script_path),          // 上一级目录
        format!("../../{}", script_path),       // 上两级目录
        format!("../scripts/{}", script_path),  // 上一级的scripts目录
        format!("scripts/{}", script_path),     // scripts子目录
        format!("./main.py"),                   // 当前目录下的main.py
        format!("../main.py"),                  // 上一级目录下的main.py
        format!("../../main.py"),               // 上两级目录下的main.py
    ];
    
    // 查找第一个存在的脚本路径
    let mut found_script_path = None;
    for path in &possible_paths {
        if std::path::Path::new(path).exists() {
            found_script_path = Some(path.clone());
            println!("✅ [Tauri] 找到Python脚本: {}", path);
            break;
        }
    }
    
    // 如果所有路径都不存在，创建一个简单的脚本
    let python_script = match found_script_path {
        Some(path) => path,
        None => {
            let tried_paths = possible_paths.join(", ");
            let warning_msg = format!("⚠️ Python脚本不存在，已尝试以下路径: {}，将创建临时脚本", tried_paths);
            println!("{}", warning_msg);
            add_log("warning", &warning_msg).await;
            
            // 创建一个简单的Python脚本
            let temp_script = "temp_crawler.py";
            let script_content = r#"
import sys
import time

print("INFO: 临时爬虫脚本启动")
print("INFO: 命令行参数:", sys.argv)

# 模拟爬虫进度
for i in range(10):
    print(f"INFO: 爬取进度 {i*10}%")
    time.sleep(1)

print("INFO: 爬取完成")
"#;
            
            // 写入临时脚本
            match tokio::fs::write(temp_script, script_content).await {
                Ok(_) => {
                    add_log("info", "✅ 已创建临时爬虫脚本").await;
                    temp_script.to_string()
                },
                Err(e) => {
                    let error_msg = format!("❌ 创建临时脚本失败: {}", e);
                    println!("{}", error_msg);
                    add_log("error", &error_msg).await;
                    return Err(AppError::Unknown(error_msg));
                }
            }
        }
    };
    
    println!("✅ [Tauri] Python脚本存在: {}", &python_script);
    
    // 设置工作目录为Python脚本所在目录，并获取文件名
    let (script_name, work_dir) = if let Some(parent_dir) = std::path::Path::new(&python_script).parent() {
        let file_name = std::path::Path::new(&python_script)
            .file_name()
            .and_then(|n| n.to_str())
            .unwrap_or("main.py");
        (file_name.to_string(), Some(parent_dir))
    } else {
        (python_script.clone(), None)
    };
    
    // 构建命令
    let mut cmd = if std::path::Path::new("uv").exists() || which::which("uv").is_ok() {
        // 如果存在uv命令，使用uv运行Python脚本
        let mut cmd = std::process::Command::new("uv");
        cmd.arg("run")
           .arg(&script_name)  // 只使用文件名
           .arg("--platform").arg(platform)
           .arg("--lt").arg("qrcode")
           .arg("--type").arg(crawler_type)
           .arg("--save_data_option").arg("sqlite");
        cmd
    } else if std::path::Path::new("python").exists() || which::which("python").is_ok() {
        // 如果存在python命令，使用python运行脚本
        let mut cmd = std::process::Command::new("python");
        cmd.arg(&script_name)
           .arg("--platform").arg(platform)
           .arg("--lt").arg("qrcode")
           .arg("--type").arg(crawler_type)
           .arg("--save_data_option").arg("sqlite");
        cmd
    } else if std::path::Path::new("python3").exists() || which::which("python3").is_ok() {
        // 如果存在python3命令，使用python3运行脚本
        let mut cmd = std::process::Command::new("python3");
        cmd.arg(&script_name)
           .arg("--platform").arg(platform)
           .arg("--lt").arg("qrcode")
           .arg("--type").arg(crawler_type)
           .arg("--save_data_option").arg("sqlite");
        cmd
    } else {
        // 如果都不存在，返回错误
        let error_msg = "❌ 未找到Python解释器，请安装Python或uv";
        println!("{}", error_msg);
        add_log("error", error_msg).await;
        return Err(AppError::Unknown(error_msg.to_string()));
    };
    
    // 设置工作目录
    if let Some(dir) = work_dir {
        cmd.current_dir(dir);
        println!("✅ [Tauri] 设置工作目录: {:?}", dir);
    }
    
    // 如果启用了评论爬取
    if config["enable_comments"].as_bool().unwrap_or(false) {
        cmd.arg("--get_comment").arg("true");
        println!("✅ [Tauri] 启用评论爬取");
    }
    
    // 如果启用了二级评论爬取
    if config["enable_sub_comments"].as_bool().unwrap_or(false) {
        cmd.arg("--get_sub_comment").arg("true");
        println!("✅ [Tauri] 启用二级评论爬取");
    }
    
    let cmd_str = format!("uv run {} --platform {} --lt qrcode --type {} --save_data_option sqlite", 
                         &python_script, platform, crawler_type);
    println!("🔧 [Tauri] 执行命令: {}", cmd_str);
    add_log("info", &format!("🔧 执行命令: {}", cmd_str)).await;
    
    add_log("info", "⏳ 正在启动Python爬虫进程...").await;
    
    // 异步启动进程，确保输出能被正确捕获
    let mut tokio_cmd = tokio::process::Command::from(cmd);
    tokio_cmd
        .stdout(std::process::Stdio::piped())
        .stderr(std::process::Stdio::piped())
        .stdin(std::process::Stdio::null())
        .kill_on_drop(true);
    
    match tokio_cmd.spawn() {
        Ok(mut child) => {
            let pid = child.id();
            println!("✅ [Tauri] Python进程启动成功，PID: {:?}", pid);
            add_log("info", &format!("✅ Python进程启动成功，PID: {:?}", pid)).await;
            
            // 获取标准输出和标准错误的句柄
            let stdout = child.stdout.take();
            let stderr = child.stderr.take();
            
            println!("📝 [Tauri] 开始捕获Python进程输出...");
            add_log("info", "📝 开始捕获Python进程输出...").await;
            
            // 处理标准输出
            if let Some(stdout) = stdout {
                println!("🔍 [Tauri] 启动stdout监听器");
                tokio::spawn(async move {
                    process_output(stdout, "stdout").await;
                    println!("🔚 [Tauri] stdout监听器结束");
                });
            } else {
                println!("⚠️ [Tauri] 无法获取stdout");
                add_log("warning", "⚠️ 无法获取Python进程的stdout").await;
            }
            
            // 处理标准错误
            if let Some(stderr) = stderr {
                println!("🔍 [Tauri] 启动stderr监听器");
                tokio::spawn(async move {
                    process_output(stderr, "stderr").await;
                    println!("🔚 [Tauri] stderr监听器结束");
                });
            } else {
                println!("⚠️ [Tauri] 无法获取stderr");
                add_log("warning", "⚠️ 无法获取Python进程的stderr").await;
            }
            
            // 保存进程句柄到全局状态
            *CRAWLER_ENGINE.write() = Some(CrawlerEngine::new_with_process(child));
            
            add_log("info", "🎯 爬虫引擎已初始化，开始监控进程状态").await;
            
            // 启动进程监控
            tokio::spawn(monitor_crawler_process());
            
            println!("🎉 [Tauri] start_crawler_process 函数执行完成");
            add_log("info", "🎉 爬虫启动流程完成，等待Python脚本输出...").await;
            Ok(())
        }
        Err(e) => {
            let error_msg = format!("❌ 启动Python进程失败: {}", e);
            println!("{}", error_msg);
            add_log("error", &error_msg).await;
            Err(AppError::Unknown(error_msg))
        }
    }
}

// 处理Python进程的输出流
async fn process_output<R>(reader: R, stream_type: &'static str) 
where
    R: tokio::io::AsyncRead + Unpin,
{
    use tokio::io::{AsyncBufReadExt, BufReader};
    
    let mut lines = BufReader::new(reader).lines();
    
    while let Ok(Some(line)) = lines.next_line().await {
        if line.trim().is_empty() {
            continue;
        }
        
        // 根据流类型和内容确定日志级别
        let level = if line.contains("ERROR") || line.contains("error") {
            "error"
        } else if line.contains("WARNING") || line.contains("warning") {
            "warning"
        } else if line.contains("INFO") || line.contains("info") {
            "info"
        } else if line.contains("DEBUG") || line.contains("debug") {
            "debug"
        } else {
            "info"
        };
        
        // 打印到控制台（带时间戳）
        let timestamp = chrono::Utc::now().format("%H:%M:%S").to_string();
        println!("[{}] [Python {}] {}", timestamp, stream_type, line);
        
        // 添加到应用日志，保持原始格式，添加Python标识
        let log_message = format!("[Python {}] {}", stream_type, line);
        add_log(level, &log_message).await;
        
        // 强制刷新输出
        use std::io::{self, Write};
        let _ = io::stdout().flush();
    }
    
    println!("[{}] Python {} stream ended", chrono::Utc::now().format("%H:%M:%S"), stream_type);
    add_log("info", &format!("Python {} 输出流结束", stream_type)).await;
}
